from tortoise.expressions import Q
from tortoise.transactions import in_transaction

from app.controllers.orders.list import orders_list_controller
from app.controllers.saas.buckling import buckling_controller
from app.controllers.saas.buckling_detail import buckling_detail_controller
from app.controllers.saas.consumables_use import consumables_use_controller
from app.controllers.saas.performance_percentage import performance_percentage_controller
from app.core.crud import CRUDBase
from app.models import BucklingDetail, OrdersList, OrdersGoods, Goods, BucklingGroup
from app.models.saas import Cases, Buckling, BucklingTodo
from app.schemas.saas import CasesCreate, CasesUpdate, BucklingDetailCreate, ConsumablesCreate, BaseConsumablesUse, \
    PerformancePercentageCreate
from app.log.log import logger

class TransactionError(Exception):
    """自定义异常类，用于事务失败时回滚"""
    pass


class CasesController(CRUDBase[Cases, CasesCreate, CasesUpdate]):
    def __init__(self):
        super().__init__(model=Cases)

    async def do_list(self, page: int, page_size: int, search: Q = Q()):
        query = self.model.filter(search)
        total = await query.count()
        objs =  await query.offset((page - 1) * page_size).limit(page_size).order_by('-id')
        data = [await obj.to_dict(exclude_fields=["updated_at","deleted_at"]) for obj in objs]
        return total, data

    async def do_detail(self,data_id:int):
        obj = await self.get(id=data_id)
        data = await obj.to_dict()
        return data

    async def do_create(self, obj_in: CasesCreate):
        try:
            async with in_transaction() as transaction:
                ret = await self.create(obj_in=obj_in)
                buckling_data = obj_in.buckling_data
                for item in buckling_data:
                    ##批量插入划扣记录
                    buckling_id = item["buckling_id"]
                    group_id=0
                    if item.get("group_id") is not None:
                        group_id = item["group_id"]
                    nums = item["nums"]
                    buckling = await Buckling.get(id=buckling_id)
                    buckling_dict = await buckling.to_dict()
                    if nums>0:
                        date_detail = BucklingDetailCreate(
                            buckling_id=buckling_id,
                            nums=nums,
                            cases_id=ret.id,
                            buckling_price=buckling_dict['price']/nums
                        )
                        await buckling_detail_controller.do_create(obj_in=date_detail)
                    else:
                        logger.info(f"划扣失败请检查数量,划扣编号: {buckling_id}")
                        raise TransactionError(f"划扣失败请检查数量,划扣编号: {buckling_id}")
                    logger.info(f"批量插入划扣记录完成: {buckling_id}")
                    ##更新buckling的使用记录和剩余数量
                    buckling_data = await Buckling.filter(id=buckling_id).first().values("use_nums","last_nums","todo_id")
                    use_nums = buckling_data["use_nums"]
                    last_nums = buckling_data["last_nums"]
                    new_use_nums = use_nums + nums
                    new_last_nums = last_nums - nums
                    if new_last_nums<0:
                        # 手动抛出异常来触发回滚
                        logger.info(f"不足划扣请检查,划扣编号: {buckling_id}")
                        raise TransactionError(f"不足划扣请检查,划扣编号: {buckling_id}")
                    logger.info(f"更新buckling的使用记录和剩余数量完成: {buckling_id}")
                    buckling = await Buckling.filter(id=item['id']).first().values()
                    ##开卡触发权益
                    # await orders_list_controller.do_give(buckling['order_id'])
                    ##更新各种状态

                    await Buckling.filter(id=buckling_id).update(use_nums=new_use_nums,last_nums=new_last_nums)
                    if group_id:
                        await BucklingGroup.filter(id=group_id).update(use_times=new_use_nums, last_times=new_last_nums)
                    logger.info(f"更新group_id完成: {buckling_id}")

                    last_nums_arr = await Buckling.filter(todo_id=buckling_data["todo_id"]).values_list('last_nums', flat=True)
                    has_positive = any(last_nums > 0 for last_nums in last_nums_arr)
                    if has_positive is False:
                        await BucklingTodo.filter(id=buckling_data["todo_id"]).update(status=2)
                    # 业绩
                    # performance_detail = PerfoBucklingTodormancePercentageCreate(
                    #     order_id=0,
                    #     goods_id=item.sku_id,
                    #     sku_id=item.sku_id,
                    #     customer_id=obj_in.user_id,
                    #     user_id=0,
                    #     space_id=obj_in.space_id,
                    #     price=0,
                    #     buckling_id=item.buckling_id,
                    #     status=0,
                    # )
                    # await performance_percentage_controller.do_create(obj_in=performance_detail)
                # 耗材
                buckling_consumables = obj_in.buckling_consumables
                if buckling_consumables:
                    for consumable in buckling_consumables:
                        ##批量插入划扣记录
                        case_id = ret.id
                        nums = consumable["nums"]
                        if nums>0:
                            date_detail = BaseConsumablesUse(
                                consumables_id=consumable["id"],
                                nums=nums,
                                cases_id=case_id,
                                user_id=obj_in.user_id
                            )
                            await consumables_use_controller.do_create(obj_in=date_detail)
                logger.info(f"更新耗材完成")

            return True
        except TransactionError:
            # 捕获自定义异常并返回 False
            return False  # 事务回滚后返回 False

        except Exception as e:
            # 其他异常捕获，确保所有错误都会返回 False
            return False


    async def do_update(self, obj_in: CasesUpdate):
        await self.update(id=obj_in.id, obj_in=obj_in)
        return True

    async def do_delete(self, data_id: int):
        async with in_transaction() as transaction:
            await self.remove(id=data_id)
            details = await BucklingDetail.filter(cases_id=data_id).all().values()
            for item in details:
                ##每一条都给他恢复
                buckling_data = await Buckling.filter(id=item["buckling_id"]).first().values("use_nums", "last_nums")
                use_nums = buckling_data["use_nums"]
                last_nums = buckling_data["last_nums"]
                new_use_nums = use_nums - item["nums"]
                new_last_nums = last_nums + item["nums"]
                await Buckling.filter(id=item["buckling_id"]).update(use_nums=new_use_nums, last_nums=new_last_nums)
                await buckling_detail_controller.do_delete(data_id=item["id"])
        return True

cases_controller = CasesController()
